/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.core.service.impl;

import com.google.common.collect.Lists;
import com.intelligent.ispc.cache.ReportCacheFactory;
import com.intelligent.ispc.common.mapper.BeanMapper;
import com.intelligent.ispc.common.persistence.SearchFilter;
import com.intelligent.ispc.core.dto.*;
import com.intelligent.ispc.core.entity.DUTAttribute;
import com.intelligent.ispc.core.entity.TestData;
import com.intelligent.ispc.core.entity.TestItem;
import com.intelligent.ispc.core.repository.mongo.TestDataDao;
import com.intelligent.ispc.core.service.ProjectService;
import com.intelligent.ispc.core.service.ReportService;
import com.intelligent.ispc.utils.PageSubList;
import com.intelligent.ispc.utils.SystemConfig;
import com.intelligent.ispc.utils.YieldType;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;

/**
 * Created by cherry on 2016/3/15.
 */
@Service
public class ReportServiceImpl extends BaseCacheServiceImpl implements ReportService {

    private static Logger logger = LoggerFactory.getLogger(ReportServiceImpl.class);

    @Autowired
    private SystemConfig systemConfig;

    @Autowired
    private ProjectService projectService;

    @Autowired
    protected ReportCacheFactory reportCacheFactory;

    @Override
    public Page<TestDataExDto> searchSerialNumber(Map<String, Object> searchParams, Pageable pageable) {
        Map<String, Object> filters = getParamsMap(searchParams);
        filters.put("isNeedItems", false);
        filters.put("isNeedDutAttributes", false);
        List<TestData> testDataList = searchTestDataList(filters, pageable);

        Long count = getTestDateCount(filters);
        List<TestDataExDto> testDataDtos = Lists.newArrayList();

        SimpleDateFormat dateFormat = new SimpleDateFormat(systemConfig.getDateFormat());
        for (TestData testData : testDataList) {
            TestDataExDto testDataDto = new TestDataExDto();
            testDataDto.setProjectId(testData.getProjectId());
            if (testData.getTestData().get(TestData.PSA_SLOT_NO) != null) {
                testDataDto.setSlotNo(testData.getTestData().get(TestData.PSA_SLOT_NO).toString());
            } else {
                testDataDto.setSlotNo("-");
            }

            if (testData.getTestData().get(TestData.PSA_START_TIME) != null) {
                testDataDto.setStartTime(dateFormat.format(new Date((Long)testData.getTestData().get(TestData.PSA_START_TIME))));

            }
            if (testData.getTestData().get(TestData.PSA_STOP_TIME) != null) {
                testDataDto.setStopTime(dateFormat.format(new Date((Long)testData.getTestData().get(TestData.PSA_STOP_TIME))));
            }

            if (testData.getTestData().get(TestData.PSA_STATION_ID) != null) {
                testDataDto.setStationId(testData.getTestData().get(TestData.PSA_STATION_ID).toString());
                testDataDto.setStationName(testData.getTestData().get(TestData.PSA_STATION_ID).toString());
            } else {
                testDataDto.setStationName("-");
            }

            testDataDto.setSerialNumber(testData.getTestData().get(TestData.PSA_SERIAL_NUMBER).toString());
            testDataDto.setIsPass((Boolean) testData.getTestData().get(TestData.PSA_IS_PASS));
            if (filters.containsKey("projectName")) {
                testDataDto.setProjectName(filters.get("projectName") == null ? "-" : filters.get("projectName").toString());
            }
            testDataDto.setIdStr(testData.getId());
            testDataDtos.add(testDataDto);
        }
        Page<TestDataExDto> pageDto = new PageImpl<TestDataExDto>(testDataDtos, pageable, count);
        return pageDto;
    }

    @Override
    public List<DUTAttributeDto> searchAttributes(Map<String, Object> searchParams) {
        Map<String, Object> filters = getParamsMap(searchParams);
        filters.put("DESC", true);

        if (filters.containsKey("startTime")) {
            filters.remove("startTime");
        }
        if (filters.containsKey("stopTime")) {
            filters.remove("stopTime");
        }
        filters.put("isNeedDutAttributes", true);
        List<TestData> testDataList = searchTestDataList(filters, null);

        List<PSAttributeDto> psAttributeDtoList = projectService.findPSAttributeByProject(filters.get("projectId").toString());
        List<DUTAttributeDto> dutAttributeDtos = Lists.newArrayList();

        for (PSAttributeDto psAttributeDto : psAttributeDtoList) {
            String psName = psAttributeDto.getName();
            if (psName == null || psAttributeDto.getIsShow() == null || !psAttributeDto.getIsShow() || psAttributeDto.getIsDefault() == null || psAttributeDto.getIsDefault()) {
                continue;
            }
            DUTAttributeDto dutAttributeDto = new DUTAttributeDto();
            dutAttributeDto.setAttributeName(psName);
            if (testDataList != null && !testDataList.isEmpty()) {
                TestData testData = testDataList.get(0);
                for (DUTAttribute dutAttribute : testData.getDutAttributes()) {
                    if (dutAttribute.getAttributeName().equals(psName)) {
                        dutAttributeDto.setAttributeValue(dutAttribute.getAttributeValue());
                        break;
                    }
                }
            }
            dutAttributeDtos.add(dutAttributeDto);
        }

        logger.debug("Searching dutAttribute, total elements:{}", dutAttributeDtos.size());

        return dutAttributeDtos;
    }

    @Override
    public List<TestItemDto> searchTestItem(Map<String, Object> searchParams) {
        Map<String, Object> filters = getParamsMap(searchParams);
        filters.put("isNeedItems", true);

        List<TestData> testDataList = searchTestDataList(filters, null);
        List<TestItemDto> testItemDtos = Lists.newArrayList();
        for (TestData testData : testDataList) {
            for (TestItem testItem : testData.getTestItems()) {
                TestItemDto testItemDto = new TestItemDto();
                BeanMapper.copy(testItem, testItemDto);
                testItemDtos.add(testItemDto);
            }
        }
        return testItemDtos;
    }

    @Override
    public Page<TestItemDto> searchTestItem(Map<String, Object> searchParams, Pageable pageable) {
        List<TestItemDto> testItemDtos = this.searchTestItem(searchParams);
        int count = testItemDtos.size();

        Page<TestItemDto> pageDto = new PageImpl<TestItemDto>(PageSubList.getPageList(testItemDtos, pageable.getPageNumber(), pageable.getPageSize(), count), pageable, count);

        return pageDto;
    }

    @Override
    public List<YieldDto> searchYield(Map<String, Object> searchParams) {
        Map<String, Object> filters = getParamsMap(searchParams);
        List<YieldDto> yieldDtos = Lists.newArrayList();

        try {
            String strList = reportCacheFactory.getCacheYield().get(mapper.toJson(filters));
            yieldDtos = mapper.fromJson(strList, mapper.contructCollectionType(List.class, YieldDto.class));

        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return yieldDtos;
    }

    @Override
    public Page<TestDataExDto> searchYieldSerialNumber(Map<String, Object> searchParams, Pageable pageable) {
        Map<String, Object> filters = getParamsMap(searchParams);
        filters.put("isNeedItems", false);
        filters.put("isNeedDutAttributes", false);
        List<TestData> testDataList = searchTestDataList(filters, pageable);

        SimpleDateFormat dateFormat = new SimpleDateFormat(systemConfig.getDateFormat());
        List<TestDataExDto> testDataExDtoList = Lists.newArrayList();
        for (TestData testData : testDataList) {
            TestDataExDto testDataExDto = new TestDataExDto();
            String serialNumber = testData.getTestData().get(TestData.PSA_SERIAL_NUMBER) == null ? null : testData.getTestData().get(TestData.PSA_SERIAL_NUMBER).toString();
            String projectId = testData.getProjectId();
            String stationId = testData.getTestData().get(TestData.PSA_STATION_ID) == null ? null : testData.getTestData().get(TestData.PSA_STATION_ID).toString();
            String testDataId = testData.getId();
            testDataExDto.setProjectId(projectId);
            testDataExDto.setSerialNumber(serialNumber);
            if (filters.containsKey("projectName")) {
                testDataExDto.setProjectName(filters.get("projectName").toString());
            }

            if (testData.getTestData().get(TestData.PSA_SLOT_NO) != null) {
                testDataExDto.setSlotNo(testData.getTestData().get(TestData.PSA_SLOT_NO).toString());
            } else {
                testDataExDto.setSlotNo("-");
            }

            testDataExDto.setIdStr(testDataId);
            testDataExDto.setStationId(stationId);
            testDataExDto.setStationName(stationId);

            if (testData.getTestData().get(TestData.PSA_IS_PASS) != null) {
                testDataExDto.setIsPass((boolean) testData.getTestData().get(TestData.PSA_IS_PASS));
            }

            if (testData.getTestData().get(TestData.PSA_START_TIME) != null) {
                String startTime = dateFormat.format(new Date((Long) testData.getTestData().get(TestData.PSA_START_TIME)));
                testDataExDto.setStartTime(startTime);

            }
            if (testData.getTestData().get(TestData.PSA_STOP_TIME) != null) {
                testDataExDto.setStopTime(dateFormat.format(new Date((Long) testData.getTestData().get(TestData.PSA_STOP_TIME))));
            }
            testDataExDtoList.add(testDataExDto);
        }
        Long count = getTestDateCount(filters);
        Page<TestDataExDto> pageDto = new PageImpl<TestDataExDto>(testDataExDtoList, pageable, count);
        return pageDto;
    }

    protected Map<String, Object> getParamsMap(Map<String, Object> paramMap) {
        Map<String, Object> filters = SearchFilter.parseParam(paramMap);
        return filters;
    }
}
